#include <iostream>
#include "Sock.hpp"
#include "Protocol.hpp"
#include "Log.hpp"

static void Usage(const std::string &process)
{
    std::cout << "\nUsage: " << process << " server_ip server_port\n"
              << std::endl;
}

//./CalClient server_ip server_port
int main(int argc, char *argv[])
{
    // 检查命令行参数，获取服务端端口号、IP地址
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }
    std::string server_ip = argv[1];
    uint16_t server_port = atoi(argv[2]);

    // 创建套接字
    Sock sock;
    int sockfd = sock.Socket();
    // 连接服务端
    if (sock.Connect(sockfd, server_port, server_ip) < 0)
    {
        std::cerr << "client:连接失败" << std::endl;
        exit(2);
    }

    // 与服务端通讯
    bool quit = false;
    std::string buffer;
    while (!quit)
    {
        std::cout << std::endl;
        std::cout << "----------------------" << std::endl;
        // 创建一个请求
        ns_protocol::Request req;
        std::cout << "Please Enter # ";
        std::cin >> req.x_ >> req.op_ >> req.y_;
        logMessage(DEBUG, "请求结果为, x:%d, y:%d, op:%c", req.x_, req.y_, req.op_);

        // 将请求序列化
        std::string send_str = req.Serialize();
        logMessage(DEBUG, "序列化结果为，%s", send_str.c_str());

        // 添加长度信息
        send_str = ns_protocol::Encode(send_str);
        logMessage(DEBUG, "添加长度信息后, %s", send_str.c_str());
        // 发送给服务端
        ns_protocol::Send(sockfd, send_str);

        // 从服务端读取结果
        while (true)
        {
            // 读取响应结果
            bool ret = ns_protocol::Recv(sockfd, buffer);
            if (!ret) // 读取失败
            {
                printf("DEBUG: 获取响应失败，退出。\n");
                quit = true; // 退出循环，关闭sockfd
                break;
            }
            // 对响应解析：是否获取到完整报文
            std::string package = ns_protocol::Decode(buffer);
            if (package.empty()) // 说明本次接收到的报文不完整，继续读取
            {
                logMessage(DEBUG, "报文不完整，继续读取。");
                continue;
            }
            logMessage(DEBUG, "读取到完整报文, %s\n", package.c_str());

            // 到此步骤，获取到了完整报文，可以反序列化
            ns_protocol::Response resp;
            resp.Deserialized(package);

            // 显示结果
            std::string err;
            switch (resp.code_)
            {
            case 1:
                err = "除零错误";
                break;
            case 2:
                err = "模零错误";
                break;
            case -1:
                err = "非法操作";
                break;
            default:
                std::cout << "result: " << resp.result_ << std::endl;
                break;
            }
            if (!err.empty()) // 显示错误信息
                std::cout << "code: " << err << std::endl;

            break;
        }
    }
    close(sockfd);

    return 0;
}